import { Algorithm } from "../types"
import { GraphLink, GraphNode } from "../types"
import { request, handleApiError } from '../utils/request'
import { v4 as uuid } from 'uuid'

// 添加AlgorithmRequest接口定义
interface AlgorithmRequest {
  task_id: string
  task_callback_url?: string
  input_params: {
    facetnet_params: {
      edges_list: number[][][]
      alpha: number
      tsteps: number
      N: number
      M: number
      with_truth: boolean
      truth_comms?: number[][][]
    }
  }
}

// 添加API响应接口定义
interface ApiResponse {
  task_status: "PENDING" | "RUNNING" | "COMPLETED" | "FAILED"
  task_progress?: number
  error_message?: string
  output_params?: {
    facetnet_results: {
      results: Array<{
        time: number;
        communities: number[];
        soft_modularity: number;
        mutual_info?: number;
        community_matrix?: number[][];
      }>;
      algorithm: string;
      parameters: Record<string, any>;
      community_results?: number[][];
    }
  }
}

// API配置
const API_CONFIG = {
  BASE_URL: 'http://172.16.4.151:1122/facetnet',
  TIMEOUT: 30000,
  MAX_POLL_ATTEMPTS: 10
}

// 通用请求函数
async function makeRequest(url: string, options: RequestInit): Promise<Response> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open(options.method || 'GET', url);
    
    // 设置完整的请求头
    xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
    xhr.setRequestHeader('Accept', '*/*');
    xhr.setRequestHeader('Accept-Language', 'zh-CN,zh;q=0.9');
    xhr.setRequestHeader('Connection', 'keep-alive');
    xhr.setRequestHeader('Cache-Control', 'no-cache');
    xhr.setRequestHeader('Pragma', 'no-cache');
    
    // 允许跨域请求
    xhr.withCredentials = false;
    
    // 设置超时
    xhr.timeout = API_CONFIG.TIMEOUT;
    
    xhr.onload = function() {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve({
          ok: true,
          status: xhr.status,
          json: async () => JSON.parse(xhr.responseText),
          text: async () => xhr.responseText
        } as Response);
      } else {
        reject(new Error(`HTTP错误 ${xhr.status}: ${xhr.responseText}`));
      }
    };
    
    xhr.onerror = function() {
      reject(new Error('网络请求失败'));
    };
    
    xhr.ontimeout = function() {
      reject(new Error('请求超时'));
    };
    
    try {
      // 确保body是字符串类型
      const body = options.body ? 
        (typeof options.body === 'string' ? options.body : JSON.stringify(options.body)) 
        : null;
      xhr.send(body);
    } catch (error) {
      reject(error);
    }
  });
}

export const dynamicGraphFacetnet: Algorithm = {
  name: "动态异构图生成算法",
  description: "基于FacetNet的动态异构图生成和社区发现算法，支持多时间步的动态网络分析",
  configOptions: [
    {
      id: "networkType",
      label: "网络类型",
      type: "select",
      options: ["社交网络", "引文网络", "协作网络", "通信网络", "生物网络"],
      defaultValue: "社交网络",
    },
    {
      id: "timeSteps",
      label: "时间步数",
      type: "number",
      defaultValue: 2,
    },
    {
      id: "nodeCount",
      label: "节点数量",
      type: "number",
      defaultValue: 4,
    },
    {
      id: "communityCount",
      label: "社区数量",
      type: "number",
      defaultValue: 2,
    },
    {
      id: "alpha",
      label: "时间平滑参数",
      type: "number",
      defaultValue: 0.9,
    }
  ],
  execute: async (config) => {
    try {
      // 记录开始时间
      const startTime = Date.now();
      
      // 生成更规范的任务ID
      const taskId = `facetnet-${uuid()}`
      
      // 准备 FacetNet API 请求数据
      const apiData: AlgorithmRequest = {
        task_id: taskId,
        task_callback_url: `${typeof window !== 'undefined' ? window.location.origin : ''}/api/callback`,
        input_params: {
          facetnet_params: {
            edges_list: Array.from({ length: config.timeSteps }, (_, t) => 
              generateEdgesList(config, t)
            ),
            alpha: config.alpha,
            tsteps: config.timeSteps,
            N: config.nodeCount,
            M: config.communityCount,
            with_truth: true,
            truth_comms: Array.from({ length: config.timeSteps }, (_, t) => 
              generateTruthComms(config, t)
            )
          }
        }
      }

      // 1. 创建任务
      console.log('正在创建 FacetNet 任务...', { taskId });
      const createResponse = await makeRequest(`${API_CONFIG.BASE_URL}/create`, {
        method: 'POST',
        body: JSON.stringify(apiData)
      });
      
      if (!createResponse.ok) {
        throw new Error('创建任务失败');
      }
      console.log('FacetNet 任务创建成功');

      // 2. 执行任务
      console.log('正在执行 FacetNet 任务...');
      const executeResponse = await makeRequest(`${API_CONFIG.BASE_URL}/execute/${taskId}`, {
        method: 'POST'
      });
      
      if (!executeResponse.ok) {
        throw new Error('执行任务失败');
      }
      console.log('FacetNet 任务开始执行');

      // 3. 轮询获取结果
      console.log('开始轮询获取结果...');
      const result = await pollResult(taskId);
      console.log('成功获取结果');
      
      // 转换结果为图可视化数据
      const graphData = convertToGraphData(result, config);
      console.log("图可视化数据统计:", { 
        节点数量: graphData.nodes.length,
        边数量: graphData.edges.length,
        数据示例: {
          节点: graphData.nodes.slice(0, 2),
          边: graphData.edges.slice(0, 2)
        }
      });
      const summary = generateSummary(result, config);

      // 添加一个更简单的数据结构以供测试
      const simpleGraphData = {
        nodes: Array.from({ length: config.nodeCount }, (_, i) => ({
          id: `${i}`,
          label: `节点${i}`,
          color: "#4285F4"
        })),
        links: Array.from({ length: config.nodeCount }, (_, i) => ({
          id: `link-${i}`,
          source: `${i}`,
          target: `${(i + 1) % config.nodeCount}`
        }))
      };

      // 返回数据，使用实际计算的执行时间
      return {
        data: {
          summary: summary,
          graphData: {
            nodes: graphData.nodes,
            edges: graphData.edges, 
            cosmographData: graphData.cosmographData
          },
          simpleGraphData: simpleGraphData,
          // 添加时间步数，供动态视图使用
          timeSteps: config.timeSteps || 3
        },
        steps: [
          "初始化FacetNet任务...",
          "生成边列表数据...",
          "设置社区真值...",
          "执行社区检测...",
          "计算节点社区归属度...",
          "生成时序演化数据...",
          "准备可视化数据..."
        ],
        // 计算实际执行时间，不依赖于taskId解析
        executionTime: `${(Date.now() - startTime).toFixed(0)}ms`,
        status: 'success'
      }
    } catch (error) {
      const errorMessage = handleApiError(error);
      throw new Error(`FacetNet 算法执行失败: ${errorMessage}`);
    }
  }
}

// 生成边列表数据函数
function generateEdgesList(config: Record<string, any>, timeStep: number) {
  const edges: [number, number][] = []
  // 生成基本的环形结构
  for (let i = 0; i < config.nodeCount; i++) {
    edges.push([i, (i + 1) % config.nodeCount])
  }
  // 添加一些随机边以增加复杂性
  for (let i = 0; i < config.nodeCount / 2; i++) {
    const source = Math.floor(Math.random() * config.nodeCount)
    let target = Math.floor(Math.random() * config.nodeCount)
    while (target === source) {
      target = Math.floor(Math.random() * config.nodeCount)
    }
    edges.push([source, target])
  }
  return edges
}

// 生成社区真值数据函数
function generateTruthComms(config: Record<string, any>, timeStep: number) {
  const comms: [number, number][] = []
  for (let i = 0; i < config.nodeCount; i++) {
    // 简单地将节点平均分配到不同社区
    comms.push([i, i % config.communityCount])
  }
  return comms
}

// 轮询获取结果函数
async function pollResult(taskId: string): Promise<ApiResponse> {
  for (let attempt = 0; attempt < API_CONFIG.MAX_POLL_ATTEMPTS; attempt++) {
    try {
      console.log(`轮询尝试 ${attempt + 1}/${API_CONFIG.MAX_POLL_ATTEMPTS}...`);
      
      const response = await makeRequest(`${API_CONFIG.BASE_URL}/result/${taskId}`, {
        method: 'GET'
      });
      
      if (!response.ok) {
        throw new Error(`获取结果失败: ${response.status}`);
      }
      
      const data: ApiResponse = await response.json();
      
      switch (data.task_status) {
        case "COMPLETED":
          // 确保返回结果包含所需的数据
          if (!data.output_params || !data.output_params.facetnet_results || !data.output_params.facetnet_results.community_results) {
            throw new Error("API返回的数据格式不正确，缺少社区结果数据");
          }
          return data;
        case "FAILED":
          throw new Error(data.error_message || "任务执行失败");
        case "PENDING":
        case "RUNNING":
          console.log(`任务状态: ${data.task_status}, 进度: ${data.task_progress || 0}%`);
          await new Promise(resolve => setTimeout(resolve, 2000));
          continue;
        default:
          throw new Error(`未知的任务状态: ${data.task_status}`);
      }
    } catch (error) {
      if (attempt === API_CONFIG.MAX_POLL_ATTEMPTS - 1) {
        throw error;
      }
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }
  throw new Error("获取结果超时");
}

// 转换结果为图可视化数据
function convertToGraphData(result: ApiResponse, config: Record<string, any>) {
  // 使用更亮的颜色，以便在暗色背景上更清晰
  const communityColors = [
    "#61AFEF", // 亮蓝色
    "#E06C75", // 亮红色
    "#98C379", // 亮绿色
    "#E5C07B", // 亮黄色
    "#C678DD", // 亮紫色
  ]

  // 添加防御性检查，确保数据存在
  if (!result.output_params || !result.output_params.facetnet_results || !result.output_params.facetnet_results.community_results) {
    console.error("缺少社区结果数据", result);
    return { 
      nodes: [], 
      edges: [], 
      cosmographData: { nodes: [], links: [] } 
    };
  }

  const communityResults = result.output_params.facetnet_results.community_results;
  
  // 获取当前时间戳作为数字
  const currentTimestamp = Date.now();
  
  // 极大程度减小节点大小的函数
  const calculateNodeSize = (value: number) => {
    // 返回一个非常小的值，确保节点不会太大
    return 0.3 + (Math.log(value) * 0.1); // 基础值0.3，对数增长非常缓慢
  };
  
  // 生成节点 - 显著减小节点大小
  const nodes = Array.from({ length: config.nodeCount }, (_, i) => {
    const communityId = i % config.communityCount;
    // 给定一个较小的基础值
    const nodeValue = 3 + Math.random() * 7; // 3-10的较小随机值
    return {
      id: `node-${i}`,
      label: `节点 ${i}`,
      type: `社区${communityId}`,
      color: communityColors[communityId],
      // 使用更小的固定大小
      size: calculateNodeSize(nodeValue),
      value: nodeValue,
      timestamp: currentTimestamp
    }
  });
  
  // 生成边 - 减少边的数量和粗细
  const edges = [];
  
  // 基本连接 - 形成一个环
  for (let i = 0; i < config.nodeCount; i++) {
    edges.push({
      id: `edge-${i}`,
      source: `node-${i}`,
      target: `node-${(i + 1) % config.nodeCount}`,
      label: "关联",
      // 使用非常小的权重值
      weight: 0.3, // 非常细的边
      timestamp: currentTimestamp
    });
  }
  
  // 添加极少量额外连接
  const extraEdgesCount = Math.min(config.nodeCount / 4, 10); // 限制额外边的数量
  for (let i = 0; i < extraEdgesCount; i++) {
    const source = Math.floor(Math.random() * config.nodeCount);
    let target = Math.floor(Math.random() * config.nodeCount);
    while (target === source) {
      target = Math.floor(Math.random() * config.nodeCount);
    }
    
    edges.push({
      id: `edge-extra-${i}`,
      source: `node-${source}`,
      target: `node-${target}`,
      label: "额外连接",
      weight: 0.2, // 极细的边
      timestamp: currentTimestamp
    });
  }
  
  // 为Cosmograph准备数据 - 针对暗色背景调整
  const cosmographData = {
    nodes: nodes.map((node) => ({
      ...node,
      // 增加一点节点大小，以便在暗色背景下更容易看见
      size: 3, 
      color: node.color,
    })),
    links: edges.map((edge) => ({
      ...edge,
      source: edge.source,
      target: edge.target,
      // 增加边的宽度，使其在暗色背景下更明显
      value: 0.5,
    })),
  };
  
  // 返回完整的数据结构
  return {
    nodes: nodes,
    edges: edges,
    cosmographData: cosmographData,
  };
}

// 生成结果摘要
function generateSummary(result: ApiResponse, config: Record<string, any>) {
  // 添加防御性检查
  if (!result.output_params || !result.output_params.facetnet_results || !result.output_params.facetnet_results.community_results) {
    return "无法生成摘要：缺少社区结果数据";
  }

  const communityResults = result.output_params.facetnet_results.community_results;
  
  const communityStats = new Array(config.timeSteps).fill(0).map(() => 
    new Array(config.communityCount).fill(0)
  )

  // 统计每个时间步中各社区的节点数量
  for (let t = 0; t < config.timeSteps; t++) {
    // 添加防御性检查，确保时间步的社区结果存在
    if (!communityResults[t]) {
      continue;
    }
    
    communityResults[t].forEach((communityId: number) => {
      if (communityId !== undefined && communityId >= 0 && communityId < config.communityCount) {
        communityStats[t][communityId]++;
      }
    })
  }

  return `分析完成！

网络基本信息:
- 时间步数: ${config.timeSteps}
- 节点数量: ${config.nodeCount}
- 社区数量: ${config.communityCount}
- 时间平滑参数: ${config.alpha}

社区分布统计:
${communityStats.map((stats, t) => 
  `时间步 ${t}:\n${stats.map((count, i) => 
    `  - 社区${i}: ${count}个节点`
  ).join("\n")}`
).join("\n\n")}`
} 